package com.xqboss.common.utils.aes;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.xqboss.common.core.domain.model.LoginBody;
import com.xqboss.common.exception.ServiceException;
import org.apache.commons.lang3.StringUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.AlgorithmParameters;
import java.security.Key;
import java.security.Security;
import java.util.Base64;


/**
 * AES 加密方法，是对称的密码算法(加密与解密的密钥一致)，这里使用128 位的密钥
 *
 * @author EDY
 */
@Component
public class AesUtil {

    private static final String STR_KEY = "D0v5EJandGoC3rpU";

    private static final String AES_IV = "b2OnvFhj3zecoNxu";

    /**
     * 只在第一次调用decrypt()方法时才new 对象
     */
    public static boolean initialized = false;

    /**
     * 加密
     */
    private static byte[] encrypt(byte[] originalContent, byte[] encryptKey, byte[] ivByte) {
        initialize();
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            SecretKeySpec skeySpec = new SecretKeySpec(encryptKey, "AES");
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(ivByte));
            byte[] encrypted = cipher.doFinal(originalContent);
            return encrypted;
        } catch (Exception e) {
            throw new ServiceException("加密异常！");
        }
    }

    /**
     * 解密
     * 填充模式AES/CBC/PKCS7Padding
     * 解密模式128
     *
     * @param content 目标密文
     */
    private static byte[] decrypt(byte[] content, byte[] aesKey, byte[] ivByte) {
        initialize();
        try {
            Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
            Key sKeySpec = new SecretKeySpec(aesKey, "AES");
            // 初始化8
            cipher.init(Cipher.DECRYPT_MODE, sKeySpec, generateIV(ivByte));
            return cipher.doFinal(content);
        } catch (Exception e) {
            throw new ServiceException("解密异常！");
        }
    }

    /**
     * BouncyCastle作为安全提供，防止我们加密解密时候因为jdk内置的不支持改模式运行报错。
     **/
    public static void initialize() {
        if (initialized) {
            return;
        }
        Security.addProvider(new BouncyCastleProvider());
        initialized = true;
    }

    /**
     * 加密
     **/
    public static String encrypt(String content) {
        byte[] encrypt = encrypt(content.getBytes(), STR_KEY.getBytes(), AES_IV.getBytes());
        return new String(Base64.getEncoder().encode(encrypt));
    }

    /**
     * 解密
     **/
    public static String decrypt(String content) {
        byte[] decode = Base64.getMimeDecoder().decode(content);
        byte[] decrypt = decrypt(decode, STR_KEY.getBytes(), AES_IV.getBytes());
        return new String(decrypt);
    }

    /**
     * 解密成对象
     **/
    public static <T> T decryptToObject(String content, Class<T> clazz) {
        if (StringUtils.isEmpty(content)) {
            throw new ServiceException("字符串不能为空！");
        }
        byte[] decode = Base64.getDecoder().decode(content);
        byte[] decrypt = decrypt(decode, STR_KEY.getBytes(), AES_IV.getBytes());
        return JSONObject.parseObject(new String(decrypt), clazz);
    }


    /**
     * 生成iv
     */
    public static AlgorithmParameters generateIV(byte[] iv) throws Exception {
        AlgorithmParameters params = AlgorithmParameters.getInstance("AES");
        params.init(new IvParameterSpec(iv));
        return params;
    }

    public static void main(String[] args) {
//        String account = "/RYrKEHfxjGWGxYuvG/K5Q==";
////        String encrypt = encrypt(account, STR_KEY, AES_IV);
//        String encrypt = encrypt(account);
//        System.out.println("加密后:" + encrypt);
//        System.out.println("解密后:" + desEncrypt("VXndikM3rgU0b6weAO+Olg==", KEY, IV));
        System.out.println("解密后 = " + decrypt("t+PM1Q8m4mhmiX83R6QZd1MKwhFEvowpqCsN6IJ5Af2qocSwP3ovwtVF/qBkZ/pl"));
        LoginBody loginBody = decryptToObject("FJqNLBua+d2M1Ewfc5/Mybpx+OEVgz64Wp3Xaf/pTsvwVb8P4cUs9KzTmFggRRiJ", LoginBody.class);
        System.out.println("loginBody = " + JSON.toJSONString(loginBody));
        /*String content ="15083500070";
        System.out.println("iv:"+IV);
        byte[] bytes = IV.getBytes();
        byte[] en= encrypt(content.getBytes(), STRKEY.getBytes(),bytes);
        System.out.println("加密:"+new String(Base64.getEncoder().encode(en)));*/
    }
}
